package cn.virens.common.mybatis.mapper.example.base;

import cn.virens.common.mybatis.entity.BaseEnum;
import cn.virens.common.mybatis.mapper.example.util.Util;
import cn.virens.common.util.exception.APIException;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("serial")
public abstract class AbstractExampleCriteriaCriterion<T> extends AbstractExampleCriteria {
    protected final List<T> criterionList = new ArrayList<>();

    public AbstractExampleCriteriaCriterion(String andOr, String condition, Object value1, Object value2) {
        super(andOr, condition, value1, value2);
    }

    public AbstractExampleCriteriaCriterion(String andOr, String condition, Object value1) {
        super(andOr, condition, value1);
    }

    public AbstractExampleCriteriaCriterion(String andOr, String condition) {
        super(andOr, condition);
    }

    /**
     * 添加is null条件(AND)
     *
     * @param column 字段
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andIsNull(String column) throws APIException {
        return addCriterion(Util.AND, column + " IS NULL");
    }

    /**
     * 添加 is not null 条件(AND)
     *
     * @param column 字段
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andIsNotNull(String column) throws APIException {
        return addCriterion(Util.AND, column + " IS NOT NULL");
    }

    /**
     * 添加等于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " =", value);
    }

    /**
     * 添加不等于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andNotEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " <>", value);
    }

    /**
     * 添加大于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andGreaterThan(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " >", value);
    }

    /**
     * 添加大于等于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andGreaterThanOrEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " >=", value);
    }

    /**
     * 添加小于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andLessThan(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " <", value);
    }

    /**
     * 添加小于等于条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andLessThanOrEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.AND, column + " <=", value);
    }

    /**
     * 添加IN条件(AND)
     *
     * @param column 字段
     * @param values 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andIn(String column, Iterable<?> values) throws APIException {
        return addCriterion(Util.AND, column + " IN", values);
    }

    /**
     * 添加NOT IN条件(AND)
     *
     * @param column 字段
     * @param values 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andNotIn(String column, Iterable<?> values) throws APIException {
        return addCriterion(Util.AND, column + " NOT IN", values);
    }

    /**
     * 添加between条件(AND)
     *
     * @param column 字段
     * @param value1 值
     * @param value2 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andBetween(String column, Object value1, Object value2) throws APIException {
        return addCriterion(Util.AND, column + " BETWEEN", value1, value2);
    }

    /**
     * 添加not between条件(AND)
     *
     * @param column 字段
     * @param value1 值
     * @param value2 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andNotBetween(String column, Object value1, Object value2) throws APIException {
        return addCriterion(Util.AND, column + " NOT BETWEEN", value1, value2);
    }

    /**
     * 添加like条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andLike(String column, String value) throws APIException {
        return addCriterion(Util.AND, column + " LIKE", value);
    }

    /**
     * 添加not like条件(AND)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andNotLike(String column, String value) throws APIException {
        return addCriterion(Util.AND, column + " NOT LIKE", value);
    }

    /**
     * 添加通用条件(AND)
     *
     * @param condition 条件
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andCondition(String condition) throws APIException {
        return addCriterion(Util.AND, condition);
    }

    /**
     * 添加通用条件(AND)
     *
     * @param condition 条件
     * @param value     值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T andCondition(String condition, Object value) throws APIException {
        return addCriterion(Util.AND, condition, value);
    }

    /**
     * 添加is null条件(OR)
     *
     * @param column 字段
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orIsNull(String column) throws APIException {
        return addCriterion(Util.OR, column + " IS NULL");
    }

    /**
     * 添加 is not null 条件(OR)
     *
     * @param column 字段
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orIsNotNull(String column) throws APIException {
        return addCriterion(Util.OR, column + " IS NOT NULL");
    }

    /**
     * 添加等于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " =", value);
    }

    /**
     * 添加不等于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orNotEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " <>", value);
    }

    /**
     * 添加大于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orGreaterThan(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " >", value);
    }

    /**
     * 添加大于等于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orGreaterThanOrEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " >=", value);
    }

    /**
     * 添加小于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orLessThan(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " <", value);
    }

    /**
     * 添加小于等于条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orLessThanOrEqualTo(String column, Object value) throws APIException {
        return addCriterion(Util.OR, column + " <=", value);
    }

    /**
     * 添加IN条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orIn(String column, Iterable<?> values) throws APIException {
        return addCriterion(Util.OR, column + " IN", values);
    }

    /**
     * 添加NOT IN条件(OR)
     *
     * @param column 字段
     * @param values 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orNotIn(String column, Iterable<?> values) throws APIException {
        return addCriterion(Util.OR, column + " NOT IN", values);
    }

    /**
     * 添加between条件(OR)
     *
     * @param column 字段
     * @param value1 值
     * @param value2 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orBetween(String column, Object value1, Object value2) throws APIException {
        return addCriterion(Util.OR, column + " BETWEEN", value1, value2);
    }

    /**
     * 添加not between条件(OR)
     *
     * @param column 字段
     * @param value1 值
     * @param value2 值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orNotBetween(String column, Object value1, Object value2) throws APIException {
        return addCriterion(Util.OR, column + " NOT BETWEEN", value1, value2);
    }

    /**
     * 添加like条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orLike(String column, String value) throws APIException {
        return addCriterion(Util.OR, column + " LIKE", value);
    }

    /**
     * 添加not like条件(OR)
     *
     * @param column 字段
     * @param value  值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orNotLike(String column, String value) throws APIException {
        return addCriterion(Util.OR, column + " NOT LIKE", value);
    }

    /**
     * 添加通用条件(OR)
     *
     * @param condition 条件
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orCondition(String condition) throws APIException {
        return addCriterion(Util.OR, condition);
    }

    /**
     * 添加通用条件(OR)
     *
     * @param condition 条件
     * @param value     值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    public T orCondition(String condition, Object value) throws APIException {
        return addCriterion(Util.OR, condition, value);
    }

    /**
     * 将查询规则添加到当前实体
     *
     * @param andOr     是否OR匹配
     * @param condition 条件
     * @return 当前实例
     * @throws APIException 一般异常
     */
    protected abstract T addCriterion(String andOr, String condition) throws APIException;

    /**
     * 将查询规则添加到当前实体
     *
     * @param andOr     是否OR匹配
     * @param condition 条件
     * @param value     条件值
     * @return 当前实例
     * @throws APIException 一般异常
     */
    protected abstract T addCriterion(String andOr, String condition, Object value) throws APIException;

    /**
     * 将查询规则添加到当前实体
     *
     * @param andOr     是否OR匹配
     * @param condition 条件
     * @param value1    条件值1
     * @param value2    条件值2
     * @return 当前实例
     * @throws APIException 一般异常
     */
    protected abstract T addCriterion(String andOr, String condition, Object value1, Object value2) throws APIException;

    /**
     * 枚举类处理
     *
     * @param value 疑似枚举对象
     * @return 枚举值或者输入值
     * @throws APIException 一般异常
     */
    protected static Object enumv(Object value) throws APIException {
        if (value != null && value instanceof BaseEnum<?>) {
            return ((BaseEnum<?>) value).getKey();
        } else {
            return value;
        }
    }

    @Override
    public boolean isVerify() throws APIException {
        return !criterionList.isEmpty();
    }

    /**
     * 获取条件列表
     *
     * @return 条件列表
     */
    public List<T> getCriterionList() {
        return criterionList;
    }

}
